const api = require("./api/index.js")
// app.js
function Dep(){
  this.subs=[]
}
Dep.prototype={
  addSubs(watcher){
    this.subs.push(watcher)
  },
  notify(){
    this.subs.forEach(watcher=>{
      watcher.update()
    })
  }
}

function Watcher(vm,exp,fn){
  this.fn=fn
  this.vm=vm
  this.exp=exp
  Dep.target=this
  let arr=exp.split('.') //这里是为了给属性每个层次绑定都绑了回调方法,还要一个作用，即可以准确到那个属性
  let val=vm
  arr.forEach(key=>{
    val=val[key]  //默认调用get方法，并且这时候的Dep.target是this,上面的订阅就会启动
  })
  Dep.target=undefined //取消
}

Watcher.prototype.update=function(){
  let arr=this.exp.split('.') 
  let val=this.vm
  arr.forEach(key=>{
    val=val[key] //这个是更新后的
  })
  this.fn(val) //使用回调函数去更新
},

App({
  onLaunch() {
    // 展示本地存储能力
    const logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)

    // 登录
    wx.login({
      success: res => {
        console.log(res)
        api.staticLogin({
          data: {
            code:res.code
          },
          success (res) {
            wx.setStorageSync('token',res.data.data)
            console.log(res.data.data);
            //避免其他页面先加载导致token没拿到
            api.defaultHeader.Authorization=res.data.data
          }
        })
      }
    })

    this.observe(this.globalData.state) //这里一定要写，绑定数据劫持
  },
  
  Observe: function (data) {
    let _this = this
    for (let key in data) {
      let val = data[key]
      this.observe(data[key])
      let dep = new Dep()   //Dep的实例可在set和get中闭包访问
                            //也就是说每个key都有对应的要通知的观察列表
      Object.defineProperty(data, key, {
        configurable: true,
        get() {
          Dep.target && dep.addSubs(Dep.target)     //获取app.globalData.wxMinix对应的值时进行订阅
          return val
        },
        set(newValue) {
          if (val === newValue) {
            return
          }
          val = newValue
          _this.observe(newValue)
          dep.notify()      // 当app.globalData.wxMinix对应的值变化时发布
        }
      })
    }
  },
  observe(data){
    if(!data||typeof data !=='object') return //如果是最末尾了就直接继续了
    this.Observe(data)
  },

  //vm代表的是app.globalData,exp是里面更具体要监视的对象，fn是回调函数主要是用来更新更具体的页面数据
  
  makeWatcher: function (key, gb, fn) {
    new Watcher(key, gb, fn)
},
  globalData: {
    state:{
      seat:"1",
      seatindex:0,
    },
    order:[],
  }
})
